home *** CD-ROM | disk | FTP | other *** search
- /*
- * rfc931_user() speaks a common subset of the RFC 931, AUTH, TAP and IDENT
- * protocols. It consults an RFC 931 etc. compatible daemon on the client
- * host to look up the remote user name. The information should not be used
- * for authentication purposes.
- *
- * Diagnostics are reported through syslog(3).
- *
- * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- *
- * Inspired by the authutil package (comp.sources.unix volume 22) by Dan
- * Bernstein (brnstnd@kramden.acf.nyu.edu).
- */
-
- #ifndef lint
- static char sccsid[] = "@(#) rfc931.c 1.5 93/07/02 16:33:36";
- #endif
-
- #include <stdio.h>
- #include <syslog.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <setjmp.h>
- #include <signal.h>
- #ifdef TLI
- #include <sys/timod.h>
- #include <stropts.h>
- #include <tiuser.h>
- #endif
-
- #include "log_tcp.h"
-
- #define RFC931_PORT 113 /* Semi-well-known port */
-
- #ifndef RFC931_TIMEOUT
- #define RFC931_TIMEOUT 30 /* wait for at most 30 seconds */
- #endif
-
- extern char *strchr();
- extern char *inet_ntoa();
-
- static jmp_buf timebuf;
-
- /* timeout - handle timeouts */
-
- static void timeout(sig)
- int sig;
- {
- longjmp(timebuf, sig);
- }
-
- /* rfc931_name - return remote user name */
-
- char *rfc931_name(there)
- struct sockaddr_in *there; /* remote link information */
- {
- struct sockaddr_in here; /* local link information */
- struct sockaddr_in sin; /* for talking to RFC931 daemon */
- int length;
- int s;
- unsigned remote;
- unsigned local;
- static char user[256]; /* XXX */
- char buffer[512]; /* YYY */
- FILE *fp;
- char *cp;
- char *result = FROM_UNKNOWN;
-
- /* Find out local address and port number of stdin. */
-
- length = sizeof(here);
- #ifdef TLI
- if (isastream(0) && ioctl(0, I_FIND, "timod") > 0) {
- struct netbuf nb;
-
- nb.buf = (char *) &here;
- nb.maxlen = length;
- if (ioctl(0, TI_GETMYNAME, &nb) < 0) {
- syslog(LOG_ERR, "TI_GETMYNAME: %m");
- return (result);
- }
- } else
- #endif
- if (getsockname(0, (struct sockaddr *) & here, &length) == -1) {
- syslog(LOG_ERR, "getsockname: %m");
- return (result);
- }
-
- /*
- * The socket that will be used for user name lookups should be bound to
- * the same local IP address as stdin. This will automagically happen on
- * hosts that have only one IP network address. When the local host has
- * more than one IP network address, we must do an explicit bind() call.
- */
-
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
- return (result);
-
- sin = here;
- sin.sin_port = 0;
- if (bind(s, (struct sockaddr *) & sin, sizeof sin) < 0) {
- syslog(LOG_ERR, "bind: %s: %m", inet_ntoa(here.sin_addr));
- return (result);
- }
- /* Set up timer so we won't get stuck. */
-
- signal(SIGALRM, timeout);
- if (setjmp(timebuf)) {
- close(s); /* not: fclose(fp) */
- return (result);
- }
- alarm(RFC931_TIMEOUT);
-
- /* Connect to the RFC931 daemon. */
-
- sin = *there;
- sin.sin_port = htons(RFC931_PORT);
- if (connect(s, (struct sockaddr *) & sin, sizeof(sin)) == -1
- || (fp = fdopen(s, "w+")) == 0) {
- close(s);
- alarm(0);
- return (result);
- }
-
- /*
- * Use unbuffered I/O or we may read back our own query. setbuf() must be
- * called before doing any I/O on the stream. Thanks for the reminder,
- * Paul Kranenburg <pk@cs.few.eur.nl>!
- */
-
- setbuf(fp, (char *) 0);
-
- /* Query the RFC 931 server. Would 13-byte writes ever be broken up? */
-
- fprintf(fp, "%u,%u\r\n", ntohs(there->sin_port), ntohs(here.sin_port));
- fflush(fp);
-
- /*
- * Read response from server. Use fgets()/sscanf() instead of fscanf()
- * because there is no buffer for pushback. Thanks, Chris Turbeville
- * <turbo@cse.uta.edu>.
- */
-
- if (fgets(buffer, sizeof(buffer), fp) != 0
- && ferror(fp) == 0 && feof(fp) == 0
- && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
- &remote, &local, user) == 3
- && ntohs(there->sin_port) == remote
- && ntohs(here.sin_port) == local) {
- /* Strip trailing carriage return. */
-
- if (cp = strchr(user, '\r'))
- *cp = 0;
- result = user;
- }
- alarm(0);
- fclose(fp);
- return (result);
- }
-